package org.ooda.distributedsys.functionmodule.function;

import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import org.ooda.distributedsys.functionmodule.common.ResponseHandler;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import registrationFun.RegistrationFun;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

/**
 * @program: distributedSys
 * @description:
 * @author: Aprilies
 * @create: 2023-08-28 17:55
 **/

// function [x_s1_with_noise,x_s2_space_aligh,x_s2_compare] = registrationFun(T,dt,theta_deg, eta_deg,v,a,x0_input,time_diff)

@RestController
@RequestMapping("dataalign")
public class DataAlignController {

    private final Queue<Runnable> requestQueue = new LinkedList<>();
    private boolean isProcessingRequest = false;

    @PostMapping("/registraion")
    public DeferredResult<ResponseEntity<?>> registraion(@RequestParam(value="T", defaultValue = "2000") double T,
                                                          @RequestParam(value="dt", defaultValue = "1") double dt,
                                                          @RequestParam(value="theta_deg", defaultValue = "45") double theta_deg,
                                                          @RequestParam(value="eta_deg", defaultValue = "0") double eta_deg,
                                                          @RequestParam(value="v", defaultValue = "1000") double v,
                                                          @RequestParam(value="a", defaultValue = "1") double a,
                                                          @RequestParam(value="x0_input", defaultValue = "1000,1000,2000") double[] x0_input,
                                                          @RequestParam(value="time_diff", defaultValue = "5") double time_diff){

        DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();

        // Create a new request task
        Runnable requestTask = () -> {
            Object[] objects = new Object[0];
            try{
                MWNumericArray T_matlab = new MWNumericArray(T, MWClassID.DOUBLE);
                MWNumericArray dt_matlab = new MWNumericArray(dt, MWClassID.DOUBLE);
                MWNumericArray theta_deg_matlab = new MWNumericArray(theta_deg, MWClassID.DOUBLE);
                MWNumericArray eta_deg_matlab = new MWNumericArray(eta_deg, MWClassID.DOUBLE);
                MWNumericArray v_matlab = new MWNumericArray(v, MWClassID.DOUBLE);
                MWNumericArray a_matlab = new MWNumericArray(a, MWClassID.DOUBLE);
                MWNumericArray x0_input_matlab = new MWNumericArray(x0_input, MWClassID.DOUBLE);
                MWNumericArray time_diff_matlab = new MWNumericArray(time_diff, MWClassID.DOUBLE);
                RegistrationFun registrationFun = new RegistrationFun();
                objects = registrationFun.registrationFun(3, T_matlab, dt_matlab, theta_deg_matlab, eta_deg_matlab, v_matlab, a_matlab, x0_input_matlab, time_diff_matlab);
                registrationFun.dispose();
                T_matlab.dispose();
                dt_matlab.dispose();
                theta_deg_matlab.dispose();
                eta_deg_matlab.dispose();
                v_matlab.dispose();
                a_matlab.dispose();
                x0_input_matlab.dispose();
                time_diff_matlab.dispose();
            }
            catch (MWException e){
                e.printStackTrace();
                deferredResult.setResult(ResponseHandler.generateResponse("error", HttpStatus.INTERNAL_SERVER_ERROR, null));
            }

            HashMap<String, double[][]> ret = new HashMap<>();
            ret.put("x_s1_with_noise", (double[][])((MWNumericArray) objects[0]).toDoubleArray());
            ret.put("x_s2_space_aligh", (double[][])((MWNumericArray) objects[1]).toDoubleArray());
            ret.put("x_s2_compare", (double[][])((MWNumericArray) objects[2]).toDoubleArray());
            ResponseEntity<?> response = ResponseHandler.generateResponse("success", HttpStatus.OK, ret);
            deferredResult.setResult(response);
            // Send the response
            synchronized (this) {
                isProcessingRequest = false;
                if (!requestQueue.isEmpty()) {
                    // If there are pending requests, process the next one
                    Runnable nextRequest = requestQueue.poll();
                    nextRequest.run();
                }
            }
        };

        if (isProcessingRequest) {
            // If another request is already being processed, enqueue the current request
            requestQueue.offer(requestTask);
        } else {
            // Process the current request
            isProcessingRequest = true;
            requestTask.run();
        }
        return deferredResult;
    }
}
